<template>
  <div class="card" ref="rootEl" :title="bookmark.title" @click="open" :style="cardStyle" :class="{ menuOpen: showMenu }">
    <button class="more" type="button" @click.stop="toggleMenu">⋯</button>
    <div v-if="showMenu" class="menu glass" @click.stop>
      <button @click="edit">编辑</button>
      <button @click="copy">复制链接</button>
      <button class="danger" @click="remove">删除</button>
    </div>
    <div class="icon" :style="iconBoxStyle">
      <img v-if="bookmark.icon && !imgError" :src="bookmark.icon" alt="icon" @error="onImgError" />
      <span v-else>{{ iconLetter }}</span>
    </div>
    <div v-if="showName" class="name">{{ bookmark.title }}</div>
  </div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, onBeforeUnmount, defineProps, defineEmits, watch } from 'vue';
import type { Bookmark } from '../../core/types/model';
import { useSettings } from '../../core/store/useSettings';
import { useBookmarks } from '../../core/store/useBookmarks';

const props = defineProps<{ bookmark: Bookmark }>();
const settings = useSettings();
const bm = useBookmarks();
const showName = computed(() => settings.settings.showName);
const iconLetter = computed(() => (props.bookmark.title?.[0] || '站').toUpperCase());
const radiusPx = computed(()=> settings.settings?.radius ?? 12);
const iconPx = computed(()=> settings.settings?.iconPx ?? (settings.settings?.iconSize==='sm'?36: settings.settings?.iconSize==='lg'?60:48));
const cardStyle = computed(() => {
  const theme = settings.theme || 'dark';
  const alpha = (() => {
    const v = Number((settings.settings as any)?.cardOpacity);
    if (!isFinite(v) || v <= 0) return theme==='light' ? 0.96 : 0.5;
    return Math.min(1, Math.max(0.2, v));
  })();
  const bg = theme==='light' ? `rgba(255,255,255,${alpha})` : `rgba(17,24,39,${alpha})`;
  // 边框透明度：
  // dark 以 #2a2e3d 为基色（42,46,61），alpha 跟随卡片透明度；
  // light 以黑色为基色，alpha 随卡片透明度线性映射（保持可见，最低 0.06）。
  const borderAlpha = theme==='light' ? Math.max(0.06, Math.min(0.28, alpha * 0.28)) : Math.min(1, Math.max(0.12, alpha));
  const borderColor = theme==='light' ? `rgba(0,0,0,${borderAlpha})` : `rgba(42,46,61,${borderAlpha})`;
  return { borderRadius: `${radiusPx.value}px`, background: bg, borderColor } as any;
});
const iconBoxStyle = computed(() => {
  // 图标圆角：当卡片圆角为0时，图标也应该是方形；否则按比例缩小（0.67倍）
  const iconRadius = radiusPx.value === 0 ? 0 : Math.max(4, Math.round(radiusPx.value * 0.67));
  return { 
    width: `${iconPx.value}px`, 
    height: `${iconPx.value}px`, 
    borderRadius: `${iconRadius}px`, 
    background: props.bookmark.color || '#2b2f3c' 
  };
});

// 图片加载失败时回退到首字母占位，避免显示浏览器的破图占位
const imgError = ref(false);
function onImgError(){ imgError.value = true; }
// 当书签图标变化时，重置错误状态以便重新尝试渲染
watch(() => props.bookmark.icon, () => { imgError.value = false; });

function open(){
  const target = settings.settings.openMode === 'newtab' ? '_blank' : '_self';
  window.open(props.bookmark.url, target);
}

// 拖拽交由外层 .bm-item 处理，避免冲突

const showMenu = ref(false);
const rootEl = ref<HTMLElement | null>(null);
function toggleMenu(){
  // 广播关闭其它卡片的菜单
  window.dispatchEvent(new CustomEvent('gce-close-all-card-menus'));
  showMenu.value = !showMenu.value;
}
const emit = defineEmits<{(e:'edit', b: Bookmark): void}>();
async function edit(){
  emit('edit', props.bookmark);
  showMenu.value = false;
}
async function remove(){
  try{
    const ok = await (window as any).gceConfirm?.('确定删除该链接？');
    if(!ok) return;
    await bm.removeBookmark(props.bookmark.id);
  }finally{
    showMenu.value = false;
  }
}
async function copy(){
  try{ 
    await navigator.clipboard.writeText(props.bookmark.url); 
    (window as any).gceToast?.('已复制链接'); 
  }catch(e){ 
    // 备用方案：使用传统方法
    const textarea = document.createElement('textarea');
    textarea.value = props.bookmark.url;
    document.body.appendChild(textarea);
    textarea.select();
    try {
      document.execCommand('copy');
      (window as any).gceToast?.('已复制链接');
    } catch {
      (window as any).gceToast?.('复制失败');
    } finally {
      document.body.removeChild(textarea);
    }
  }
  showMenu.value = false;
}

function onDocClick(e: MouseEvent){
  if(!showMenu.value) return;
  const el = rootEl.value;
  if(el && !el.contains(e.target as Node)){
    showMenu.value = false;
  }
}

function onCloseAll() { 
  showMenu.value = false; 
}

// 使用ref保存函数引用，确保内存清理
const docClickHandler = ref(onDocClick);
const closeAllHandler = ref(onCloseAll);

onMounted(()=>{
  // 使用捕获阶段，避免子元素 .stopPropagation 阻止文档监听
  document.addEventListener('pointerdown', docClickHandler.value, true);
  window.addEventListener('wetab-close-all-card-menus', closeAllHandler.value);
});

onBeforeUnmount(()=>{
  document.removeEventListener('pointerdown', docClickHandler.value, true);
  window.removeEventListener('wetab-close-all-card-menus', closeAllHandler.value);
});
</script>
<style scoped>
.card{ position:relative; display:flex; flex-direction:column; align-items:center; justify-content:center; background: var(--glass-dark); border:1px solid var(--border); cursor:pointer; user-select:none; transition: transform .18s ease, box-shadow .18s ease, background-color .18s ease; padding:12px; gap:10px; backdrop-filter: blur(4px); min-width:0; width:100%; max-width:100%; box-sizing:border-box }
.card:hover{ transform: translateY(-1px); box-shadow: var(--shadow-dark) }
.card:focus-visible{ outline:2px solid var(--primary); outline-offset:2px }
.icon{ display:flex; align-items:center; justify-content:center; background: #2b2f3c; color:#fff; font-weight:600; overflow:hidden }
.icon img{ width:100%; height:100%; object-fit: cover }
.icon span{ display:inline-block }
.name{ font-size:12px; color:var(--text); opacity:.8; width:100%; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:center; box-sizing:border-box; padding:0 2px }
.more{ position:absolute; top:6px; right:6px; width:24px; height:24px; border-radius:6px; border:1px solid var(--border); background:var(--card); color:var(--text); cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; line-height:1; opacity:0; transition: opacity .2s ease }
.card:hover .more, .card.menuOpen .more{ opacity:1 }
.menu{ position:absolute; top:34px; right:6px; display:flex; flex-direction:column; gap:6px; background:var(--glass-dark); backdrop-filter: blur(6px); border:1px solid var(--border); border-radius:10px; padding:6px; box-shadow: var(--shadow-dark); z-index: 99991; pointer-events:auto; min-width:100px }
.card.menuOpen{ z-index: 99990 }
.menu button{ background:transparent; border:0; color:var(--text); padding:6px 10px; text-align:left; border-radius:8px; cursor:pointer; white-space:nowrap }
.menu button:hover{ background: rgba(255,255,255,.06) }
.menu .danger{ color:#ef4444 }

/* light 主题：与搜索框一致的玻璃风格 */
:host-context([data-theme='light']) .card{ background: var(--glass-light); border-color: var(--border-light) }
:host-context([data-theme='light']) .card:hover{ box-shadow: var(--shadow-light) }
:host-context([data-theme='light']) .icon{ background: #f1f5f9; color:#111 }
</style>
